﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Asp = System.Web.UI.WebControls.WebParts;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;

namespace Mystery.SharePoint
{
	public class WikiPageModification
	{
		private const string CustomizedKey = "SPM.Customized";

		SPFile _file;
		SPLimitedWebPartManager _manager;
		string _template;
		Dictionary<string, Asp.WebPart> _positionMapping = new Dictionary<string, Asp.WebPart>();
		Dictionary<string, Guid> _keyMapping = new Dictionary<string, Guid>();
		private bool _customized = false;

		/// <summary>
		/// Constructs an object that can be used to modify a wiki page
		/// </summary>
		/// <param name="file">The file representing the wiki page</param>
		public WikiPageModification(SPFile file)
		{
			if (file == null) throw new ArgumentNullException("file");
			if (file.Item.Fields.FindById(SPBuiltInFieldId.WikiField) == null) 
				throw new ArgumentOutOfRangeException("The file is missing the wiki field");

			_file = file;
			_manager = _file.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
			_customized = Convert.ToBoolean(_file.Item.Properties.Read<string>(CustomizedKey, false.ToString()));
		}
		/// <summary>
		/// Loads content to use as a template. Specify placeholder inside [ ]. i.e. [Documents]
		/// </summary>
		/// <param name="content"></param>
		public void LoadTemplate(string content)
		{
			_template = content;
		}
		/// <summary>
		/// Commits changes 
		/// </summary>
		public void Commit()
		{
			// only update the home page once
			if(_customized == false)
			{
				// remove any existing web parts
				while (_manager.WebParts.Count > 0)
				{
					_manager.DeleteWebPart(_manager.WebParts[0]);
				}
				_file.Item[SPBuiltInFieldId.WikiField] = ExpandTemplate();
				_file.Item.Properties.Write(CustomizedKey, true.ToString());
				_file.Item.UpdateOverwriteVersion();
			}
			_manager.Dispose();
		}

		public void Register(Asp.WebPart webPart, string placeholder)
		{
			// store a guid here, will be reformatted later into a storage id
			webPart.ID = Guid.NewGuid().ToString("D");
			_positionMapping.Add(placeholder, webPart);
		}
		public Asp.WebPart Register(SPList list, string placeholder)
		{
			Asp.WebPart part = SPWebPartManager.CreateWebPartFromList(list, false);
			Register(part, placeholder);
			return part;
		}

		private string ExpandTemplate()
		{
			string s = _template;

			foreach (string key in _positionMapping.Keys)
			{
				Asp.WebPart part = _positionMapping[key];
			
				s = s.Replace("[" + key + "]", Render(part.ID));

				// reformat the id and add it to the web part zone
				part.ID = "g_" + part.ID.Replace('-', '_');
				_manager.AddWebPart(part, "wpz", 0);
			}
			return s;
		}
	
		private string Render(string id)
		{
			return 
				"		<div class=\"ms-rtestate-read ms-rte-wpbox\" contentEditable=\"false\">" +
				"			<div class=\"ms-rtestate-read " + id + "\" id=\"div_" + id + "\" />" +
				"			<div style='display:none' id=\"vid_" + id + "\" />" +
				"		</div>";
		}
	}
}
